import serial
import serial_packets
import traceback

from Queue import PriorityQueue

from serial.serialutil import SerialException

class Arduino:
  def __init__(self, settings):
    self.arduino = ''
    self.tries = settings.arduino_conn_tries
    self.baud = settings.baud_rate
    self.timeout = settings.serial_timeout
    self.latest_firmware = settings.latest_firmware
    self.ard_ack_message = settings.ard_ack_message

  def connect(self):
    conn_cardinal = 0
    while(conn_cardinal < self.tries):
      try:
        self.arduino = serial.Serial(conn_cardinal)
        self.arduino.baudrate = self.baud
        self.arduino.timeout = self.timeout

        if self.verify(self.ard_ack_message):
          return [True, self.arduino.port]

      except OSError, e:
        conn_cardinal+=1
      except Exception, e:
        conn_cardinal+=1
        traceback.print_exc()

    return [False]

  def verify(self, latest_firmware):
    try:
      result = self.recieve()[1]

      if self.ard_ack_message in result:
        len = int(self.ard_ack_message.__len__())

        version = int(result[len:])

        if version == int(self.latest_firmware):
          return True
        else:
          raise EnvironmentError("Arduino out of date, " + str(version) + " vs " + str(self.latest_firmware))

    except Exception, e:
      raise

    return False

  def initialize(self, image_width):
    packet = serial_packets.InitializationCmd(image_width)

    self.send(packet)

    result = self.recieve()
    return result

  def send(self, command):
    if(not self.arduino.isOpen()):
      self.arduino.open()

    command_string = command.__str__()

    self.arduino.write(command_string)
    self.arduino.flushOutput()

  def recieve(self):
    if(not self.arduino.isOpen()):
      self.arduino.open()

    result = self.arduino.readline()
    
    return self.parseResponse(result)

  def disconnect(self):
    if(self.arduino.isOpen()):
      self.arduino.close()
  
  def parseResponse(self, response):
    values = [ x.strip() for x in response.split(',') ]
    values[-1] = values[-1].replace(';', '')
    return values
